package com.tbit.uqbike.service.business.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tbit.common.constant.BalanceLogCapitalTypeContent;
import com.tbit.common.constant.BalanceLogChangeTypeContent;
import com.tbit.common.constant.IncomeTypeContent;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.service.business.ReturnDepositService;
import com.tbit.uqbike.service.business.UserAccountLogService;
import com.tbit.uqbike.service.business.UserService;
import com.tbit.uqbike.service.rpcservice.MachineBorrowService;
import com.tbit.uqbike.webmanager.dao.capital.BalanceChangeDao;
import com.tbit.uqbike.webmanager.dao.capital.MoneyOpeLogDao;
import com.tbit.uqbike.webmanager.dao.capital.UserCapitalChangeDao;
import com.tbit.uqbike.webmanager.dao.core.ReturnDepositDao;
import com.tbit.uqbike.webmanager.dao.core.UserAccountMoneyDao;
import com.tbit.uqbike.webmanager.dao.core.WeixinDepositLogDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author NINGMEI
 */
@Service("returnDepositService")
public class ReturnDepositServiceImpl implements ReturnDepositService {
    @Autowired
    private ReturnDepositDao returnDepositDao;
    @Autowired
    private UserService userService;
    @Autowired
    private MachineBorrowService machineBorrowService;
    @Autowired
    private UserAccountLogService userAccountLogService;
    @Autowired
    private WeixinDepositLogDao weixinDepositLogDao;
    @Autowired
    private BalanceChangeDao balanceChangeDao;
    @Autowired
    private UserCapitalChangeDao userCapitalChangeDao;
    @Resource
    private UserAccountMoneyDao userAccountMoneyDao;
    @Resource
    private MoneyOpeLogDao moneyOpeLogDao;

    @Override
    public Integer queryCount(Integer accountId, Integer state, List<Integer> userIds, String startTime, String endTime) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("accountId", accountId);
        params.put("state", state);
        params.put("userIds", userIds);
        params.put("startTime", startTime);
        params.put("endTime", endTime);

        return returnDepositDao.queryCount(params);
    }

    @Override
    public List<ReturnDeposit> queryPage(Integer accountId, Integer state, List<Integer> userIds, String startTime, String endTime, Integer rowCount, Integer pageNO) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("accountId", accountId);
        params.put("state", state);
        params.put("userIds", userIds);
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        params.put("start", (pageNO - 1) * rowCount);
        params.put("rowCount", rowCount);

        return returnDepositDao.queryPage(params);
    }

    @Override
    public void manualDepositRefund(Integer userId, String remark, Date returnTime, Integer operatorId,
                                    String operatorPhone, String operatorName) {
        User user = userService.getByUserId(userId);
        if (user == null) {
            throw new BaseException(SystemCodeEnum.USER_NOT_EXIST);
        }
        Integer depositMoney = user.getDepositMoney();
        if (depositMoney == 0) {
            return;
        }
        //用户借车记录
        MachineBorrow machineBorrow = machineBorrowService.getByUserId(userId);
        if (machineBorrow != null) {
            throw new BaseException(SystemCodeEnum.USER_HAVE_BORROWMACHINE);
        }
        remark = "人工扣除押金-" + remark;
        Integer brandId = user.getAccountId();

        //修改用户状态,重置押金金额为0
        userService.updateDeposit(userId, 0, 0);

        //用户资金变动表记录人工清除押金
        saveUserAccountLog(brandId, userId, depositMoney, remark);

        updateWeixinDepositLog(remark, userId, returnTime);

        processUserDeposit(userId, brandId, user, operatorId, operatorPhone, operatorName, remark, returnTime.getTime());

    }

    private void processUserDeposit(Integer userId, Integer brandId, User user, Integer operatorId,
                                    String operatorPhone, String operatorName, String remark, long time) {
        LambdaQueryWrapper<UserAccountMoney> queryWrapper = Wrappers.lambdaQuery(UserAccountMoney.class)
                .eq(UserAccountMoney::getUserId, userId)
                .eq(UserAccountMoney::getMoneyType, 2)
                .gt(UserAccountMoney::getMoney, 0);
        List<UserAccountMoney> accountDepositMoneyList = userAccountMoneyDao.selectList(queryWrapper);
        if (CollUtil.isNotEmpty(accountDepositMoneyList)) {
            for (UserAccountMoney userAccountMoney : accountDepositMoneyList) {
                updateUserAccountMoney(userId, brandId, user, operatorId, operatorPhone, operatorName,
                        remark, time, userAccountMoney);
            }
        } else {
            userAccountMoneyDao.update(new UserAccountMoney(user.getUserId(), user.getPhone(), -1, user.getAccountId(), 0L, time, 2, ""),
                    new UpdateWrapper<UserAccountMoney>().eq("userId", user.getUserId()).eq("accountId", -1).eq("moneyType", 2));
            createUserCapitalChange(userId, brandId, user, operatorId, operatorPhone, operatorName,
                    remark, time, -1, user.getDepositMoney().longValue());
            createBalanceChange(userId, brandId, user, remark, time, -1,
                    user.getDepositMoney().longValue());
            insertMoneyOpeLog(brandId, user.getDepositMoney(), time, user.getUserId(),
                    user.getPhone(), operatorId, operatorPhone, remark);
        }
    }

    private void updateUserAccountMoney(Integer userId, Integer brandId, User user, Integer operatorId,
                                        String operatorPhone, String operatorName, String remark, long time,
                                        UserAccountMoney userAccountMoney) {
        Integer accountId = userAccountMoney.getAccountId();
        Long deductionMoney = userAccountMoney.getMoney();
        userAccountMoneyDao.update(new UserAccountMoney(user.getUserId(), user.getPhone(), accountId, user.getAccountId(), 0L, time, 2, ""),
                new UpdateWrapper<UserAccountMoney>().eq("userId", user.getUserId()).eq("accountId", accountId).eq("moneyType", 2));
        createUserCapitalChange(userId, brandId, user, operatorId, operatorPhone, operatorName,
                remark, time, accountId, deductionMoney);
        createBalanceChange(userId, brandId, user, remark, time, accountId, deductionMoney);
        insertMoneyOpeLog(brandId, deductionMoney.intValue(), time, user.getUserId(),
                user.getPhone(), operatorId, operatorPhone, remark);
    }

    private void saveUserAccountLog(Integer brandId, Integer userId, Integer money, String remark) {
        UserAccountLog userAccountLog = new UserAccountLog();
        userAccountLog.setAccountId(brandId);
        userAccountLog.setUserId(userId);
        userAccountLog.setMoneyType(0);
        userAccountLog.setType(0);
        userAccountLog.setMoney(money);
        userAccountLog.setOperaTime(new Date());
        userAccountLog.setRemark(remark);
        userAccountLogService.insert(userAccountLog);
    }

    private void updateWeixinDepositLog(String remark,Integer userId,Date returnTime) {
        WeixinDepositLog weixinDepositLog = new WeixinDepositLog();
        weixinDepositLog.setRemark(remark);
        weixinDepositLog.setUserId(userId);
        weixinDepositLog.setReturnTime(returnTime);
        weixinDepositLogDao.updateRecharge(weixinDepositLog);
    }

    private void createUserCapitalChange(Integer userId, Integer brandId, User user, Integer operatorId,
                                         String operatorPhone, String operatorName, String remark,
                                         long time, Integer accountId, Long deductionMoney) {
        UserCapitalChange userCapitalChange = new UserCapitalChange(null, userId, user.getPhone(),
                user.getName(), accountId,brandId, deductionMoney, deductionMoney, 0L,
                IncomeTypeContent.inComeRefund, BalanceLogChangeTypeContent.capitalType_deposit,
                BalanceLogCapitalTypeContent.MANUAL_DEPOSIT_DEDUCTION, "", operatorId, operatorPhone, operatorName,
                "", "", time, remark, accountId);
        userCapitalChangeDao.insert(userCapitalChange);
    }

    private void insertMoneyOpeLog(Integer brandId, Integer money, long time, Integer userId, String userPhone,
                                   Integer operatorId, String operatorPhone, String remark) {
        moneyOpeLogDao.insert(new MoneyOpeLog(brandId, 3, 0, money, DateUtil.date(time), userId,
                userPhone, operatorId, operatorPhone, remark));
    }

    private void createBalanceChange(Integer userId, Integer brandId, User user, String remark, long time,
                                     Integer accountId, Long deductionMoney) {
        BalanceChange balanceChange = new BalanceChange(null, userId, user.getPhone(), user.getName(),
                accountId, brandId, deductionMoney, deductionMoney, 0L, IncomeTypeContent.inComeRefund,
                BalanceLogChangeTypeContent.capitalType_deposit, BalanceLogCapitalTypeContent.MANUAL_DEPOSIT_DEDUCTION,
                time, remark, "");
        balanceChangeDao.insert(balanceChange);
    }

}